package com.weipai.demo.util;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * @author songmengqiang
 * @create 2018-08-21 10:53
 **/

public class PasswordHelper {

    private static final Logger logger = LoggerFactory.getLogger(PasswordHelper.class);

    private final int hashIterations = 1;

    public static String encryptPassword(String pwd, String salt) {
        SimpleHash simpleHash = new SimpleHash("MD5", pwd, ByteSource.Util.bytes(salt));
        return simpleHash.toHex();
    }

    public static String generateToken(String username, int expire, String secretKey) {
        String token = null;
        //token-结构
        //base64(username-expire)@hash(base64(username-expire)+secret)
        String authInfo = username + "-" + expire;
        try {
//          String authInfoBase64 = Base64.getEncoder().encodeToString(authInfo.getBytes("utf-8"));
            String authInfoBase64 = Hex.encodeHexString(Base64.getEncoder().encode(authInfo.getBytes("utf-8")));
            Mac sha256HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("utf-8"), "HmacSHA256");
            sha256HMAC.init(secretKeySpec);
            byte[] bytes = sha256HMAC.doFinal(authInfoBase64.getBytes("utf-8"));
            token = authInfoBase64 + "@" + Hex.encodeHexString(bytes);
        } catch (UnsupportedEncodingException e) {
            logger.error("generateToken encode UnsupportedEncodingException = {}", e);
        } catch (NoSuchAlgorithmException e) {
            logger.error("generateToken encode NoSuchAlgorithmException = {}", e);
        } catch (InvalidKeyException e) {
            logger.error("generateToken encode InvalidKeyException = {}", e);
        }
        return token;
    }

    public static boolean validateToken(String authToken) {
        //token-结构
        //base64(username-expire)@hash(base64(username-expire)+secret)
        if (authToken == null) {
            return false;
        }
        String[] tokens = authToken.split("@");

        if (tokens.length != 2) {
            logger.error("invalid token error");
            return false;
        }

        String authInfoBase64 = tokens[0];

        String authInfo = null;
        try {
            authInfo = new String(Base64.getDecoder().decode(Hex.decodeHex(authInfoBase64.toCharArray())), "utf-8");
        } catch (UnsupportedEncodingException e) {
            logger.error("UnsupportedEncodingException error={}", e);
        } catch (DecoderException e) {
            logger.error("DecoderException error={}", e);
        }
        int pos = authInfo.indexOf("-");
        String username = authInfo.substring(0, pos);
        int expire = Integer.valueOf(authInfo.substring(pos + 1));

        int now = (int) (System.currentTimeMillis() / 1000);

        if (expire < now) {
            logger.error("token expire error");
            return false;
        }

        //生成token
        String newToken = PasswordHelper.generateToken(username, expire, PropUtils.getString("system.secretKey"));
        return authToken.equals(newToken);
    }

    public static String getUserName(String authToken) {
        String[] tokens = authToken.split("@");
        String authInfoBase64 = tokens[0];
        String authInfo = null;
        try {
            authInfo = new String(Base64.getDecoder().decode(Hex.decodeHex(authInfoBase64.toCharArray())), "utf-8");
        } catch (UnsupportedEncodingException e) {
            logger.error("UnsupportedEncodingException error={}", e);
        } catch (DecoderException e) {
            logger.error("DecoderException error={}", e);
        }
        int pos = authInfo.indexOf("-");
        String username = authInfo.substring(0, pos);
        return username;
    }
}
